/*
* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const { WsClient2 } = require("../../engine/ws/WsClient2");
const { LogManager } = require("../ros1/LogManager");
const { PackageTool } = require("./PackageTool");

class RosProto {
    constructor() {
    }
    static registProcess() {
        WsClient2.registProcess("get_file_ret", (pt_ret) => {
            let retPath = pt_ret.get_string();
            if (retPath in RosProto.GET_FILE_CALLBACK) {
                if (pt_ret.get_bool()) {
                    // let fileLength = pt_ret.get_uint32();
                    let fileData = pt_ret.get_byte_array();
                    RosProto.GET_FILE_CALLBACK[retPath](fileData);
                } else {
                    LogManager.E("获取文件失败:", retPath);
                    RosProto.GET_FILE_CALLBACK[retPath](null);
                }
            }
        });
        WsClient2.registProcess("query_topic_msg_type_ret", (pt_ret) => {
            let success = pt_ret.get_string();
            if (success == 'ok') {
                let topicName = pt_ret.get_string();
                const { RuntimeManager } = require("../ros1/0/RuntimeManager");
                let topics = RuntimeManager.getInstance().topics;
                if (topicName in topics) {
                    let msgType = pt_ret.get_string();
                    topics[topicName].msgType = msgType;
                    const { EnvManager } = require("../ros1/EnvManager");
                    EnvManager.getInstance().addMsgObj(msgType);
                }
            }
        })
        WsClient2.registProcess("subscribe_topic_ret", (pt_ret) => {//返回的订阅消息，根据msg解析
            let topic_name = pt_ret.get_string();
            let msg_name = pt_ret.get_string();
            // console.log("subscribe_topic_ret", topic_name, msg_name);
            const { EnvManager } = require("../ros1/EnvManager");
            let msgObj = EnvManager.getInstance().getMsgObj(msg_name);
            if (msgObj) {
                // let t1 = Date.now()
                let msg = msgObj.get_msg(pt_ret);
                // console.log("get_msg cost:", Date.now() - t1);
                const { RuntimeManager } = require("../ros1/0/RuntimeManager");
                let topics = RuntimeManager.getInstance().topics;
                if (topic_name in topics) {
                    topics[topic_name].onSubscribe(msg);
                    RosProto.subscribeTopic(topic_name, 2);
                }
            }
        });
        WsClient2.registProcess("echo_ret", (pt_ret) => {
            let n = pt_ret.get_uint32();
            // console.log("echo_ret", n);
            RosProto.echo(n + 1);

            let t = Date.now();
            RosProto.ttt2++;
            if (t - RosProto.ttt > 1000) {
                // console.log("echo_ret cost:", t - RosProto.ttt, "ttt2:", RosProto.ttt2);
                RosProto.ttt = t;
                RosProto.ttt2 = 0;
            }
        });
        WsClient2.registProcess("deploy_context_ret", (pt_ret) => {
            let progress = pt_ret.get_float32();
            let message = pt_ret.get_string();
            RosProto.ON_PROGRESS(progress, message);
        });
        WsClient2.registProcess("download_file", (pt) => {
            let url = pt.get_string();
            fetch(url)
                .then(response => response.arrayBuffer())
                .then(arrayBuffer => {
                    let pt_ret = new PackageTool(arrayBuffer.byteLength + 1024);
                    pt_ret.put_string("download_file_ret");
                    pt_ret.put_string(url);
                    pt_ret.put_bool(true);
                    pt_ret.put_uint32(arrayBuffer.byteLength);
                    pt_ret.put_uint32(0);
                    pt_ret.put_uint32(arrayBuffer.byteLength);
                    pt_ret.put_byte_array(new Uint8Array(arrayBuffer));
                    WsClient2.send(pt_ret);
                });
        });
        WsClient2.registProcess("collect_messages_ret", (pt_ret) => {
            let path = pt_ret.get_string();
            let msgs = pt_ret.get_string_array();
            const { EnvManager } = require("../ros1/EnvManager");
            let mm = EnvManager.getInstance();
            mm.msgValues = {
                "原生类型": ["bool", "byte", "char", "duration", "float32", "float64", "int16", "int32", "int64", "int8", "string", "time", "uint16", "uint32", "uint64", "uint8",],
                // "自定义类型": [],
            };
            mm.msgKeys = [
                // "原生类型",
                // "自定义类型"
            ];
            for (let msg of msgs) {
                let [pkg, msg_name] = msg.split("/");
                if (!(pkg in mm.msgValues)) {
                    mm.msgValues[pkg] = [];
                    mm.msgKeys.push(pkg);
                }
                mm.msgValues[pkg].push(msg_name);
            }
            {//把msgKeys中std_msgs移动到msgKeys的第一个位置
                let std_msgs_index;
                std_msgs_index = mm.msgKeys.indexOf("sensor_msgs");
                if (std_msgs_index > 0) {
                    mm.msgKeys.splice(std_msgs_index, 1);
                    mm.msgKeys.unshift("sensor_msgs");
                }
                std_msgs_index = mm.msgKeys.indexOf("std_msgs");
                if (std_msgs_index > 0) {
                    mm.msgKeys.splice(std_msgs_index, 1);
                    mm.msgKeys.unshift("std_msgs");
                }
            }
            mm.msgKeys.unshift("原生类型");
        });
        WsClient2.registProcess("custom_node_operate_ret", (pt_ret) => {
            let token = pt_ret.get_string();
            let status = pt_ret.get_string();
            let log = pt_ret.get_string();

            const { CustomManager } = require("../ros1/1/CustomManager");
            let nom = CustomManager.getInstance().search(token);
            if (nom) {
                if (status == "err") {
                    LogManager.E("[" + nom.name + "]:" + log);
                } else {
                    LogManager.I("[" + nom.name + "]:" + log);
                }
            }
        });
    }
    static ttt = 0;
    static ttt2 = 0;
    static echo(n = 1) {
        let pt = new PackageTool();
        pt.put_string("echo");
        pt.put_uint32(n);
        for (let i = 0; i < 1; i++) {
            pt.put_uint32(i);
        }
        WsClient2.send(pt);
    }
    static ON_PROGRESS = null;
    static deployContext(rosType, onProgress, isStart = true) {//ros1,ros2,dora
        RosProto.ON_PROGRESS = onProgress;
        let pt = new PackageTool();
        pt.put_string("deploy_context");
        pt.put_string(rosType);
        pt.put_bool(isStart);
        WsClient2.send(pt);
    }
    static GET_FILE_CALLBACK = {}
    static getFile(fPath, callback) {//从板子拿文件过来
        RosProto.GET_FILE_CALLBACK[fPath] = callback;
        let pt = new PackageTool();
        pt.put_string("get_file");
        pt.put_string(fPath);
        WsClient2.send(pt);
    }
    static putFile(fPath, size, content) {//把文件上传到板子
        let pt = new PackageTool(null, size + 1024);
        pt.put_string("put_file");
        pt.put_string(fPath);
        // pt.put_uint32(size);
        pt.put_byte_array(content);
        WsClient2.send(pt);
    }
    static getRosState() {//获取ros状态，节点,发布者,订阅者,服务
        let pt = new PackageTool();
        pt.put_string("get_ros_state");
        WsClient2.send(pt);
    }
    static subscribeTopic(topic, operate) {//operate:0取消订阅,1订阅,2收到订阅
        let pt = new PackageTool()
        pt.put_string("subscribe_topic");
        pt.put_string(topic);
        pt.put_uint8(operate);
        WsClient2.send(pt);
    }
    static queryTopicMsgType(topic) {
        let pt = new PackageTool()
        pt.put_string("query_topic_msg_type");
        pt.put_string(topic);
        WsClient2.send(pt);
    }
    static queryMsgDefine(name) {
        let pt = new PackageTool()
        pt.put_string("query_msg_define");
        pt.put_string(name);
        WsClient2.send(pt);
    }
    static collectMessages() {
        let pt = new PackageTool()
        pt.put_string("collect_messages");
        pt.put_string("/opt/ros/noetic/share");
        WsClient2.send(pt);
    }
    static customNodeOperate(name, token, operate, fn, code) {
        let pt = new PackageTool()
        pt.put_string("custom_node_operate");
        pt.put_string(name);
        pt.put_string(token);
        pt.put_string(operate);//['start','stop','reload']
        pt.put_string(fn);
        pt.put_string(code);
        WsClient2.send(pt);
    }
}

module.exports = {
    RosProto
};